﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class GameManager : BaseManager {
    //采用线程下载时，存储已经下载成功的文件
    //private List<string> downloadFiles = new List<string>();
    //游戏资源解包:将游戏初始app包自带的资源ab解包释放，存放到对应平台的持久化存储目录内（MainUtil.DataPath），之后再根据自带的资源版本文件与服务器
    //的进行比对，之后将变化的资源进行更新.将ab加载到本地后，再启动游戏，所需ab从本地持久化目录里获取
    void Start () {
        Init();
	}
    void Init()
    {
        Screen.sleepTimeout = SleepTimeout.NeverSleep;
        Application.targetFrameRate = MainConst.GameFrameRate;
        CheckExtractResource();
    }

    /// <summary>
    /// 解压释放资源，并比对更新资源
    /// </summary>
    public void CheckExtractResource()
    {
        Debug.Log("当前所在的目标本地平台版本文件路径:" + MainConfigPath.PersistentDataPath() + "version.txt");
        //判断某一路径下是否存在某个目录或文件时 不要带file：,否则识别不出，这里给个临时的地址用于判断
        string path = MainConfigPath.PersistentDataPath_IO();// Application.persistentDataPath + "/" + MainConst.AppName + "/";
        //MainUtil.Log("PersistentDataPath:" + MainConfigPath.PersistentDataPath());
        //MainUtil.Log("StreamingAssetsPath:" + MainConfigPath.StreamingAssetsPath());
        //MainUtil.Log("dataPath:" + Application.dataPath);
        bool isExists = Directory.Exists(path) && File.Exists(path + "version.txt");/*Directory.Exists(MainUtil.DataPath + "dll/")*/
        MainUtil.Log("version.txt isExist:" + isExists);

        if (MainConst.DebugMode)
        {
            StartCoroutine(OnResourceInited());
        }
        else
        {
            if (/*MainConst.DebugMode ||*/ isExists)
            {
                StartCoroutine(OnUpdateResource());
                return;   //文件已经解压过了，可添加检查文件列表逻辑
            }
            //本地没有发现version文件即没释放过资源,第一次释放
            StartCoroutine(OnExtractResource());    //启动释放协程 
        }
    }

    /// <summary>
    /// 释放本地资源
    /// </summary>
    /// <returns></returns>
    IEnumerator OnExtractResource()
    {
        string dataPath = MainConfigPath.PersistentDataPath_IO();  //数据目录,既ab下载后的本地平台存储目录路径
        string resPath = MainConfigPath.StreamingAssetsPath_IO(); //游戏包资源目录，既ab资源在工程内的路径
        //string assemblySavePath = MainConfigPath.PersistentDataPath_IO() + "Assembly-CSharp.dll";//assembly要写入的本地路径
        //string assemblyReadPath = MainConfigPath.StreamingAssetsPath_IO() +"../"+ "Assembly-CSharp.dll";//assembly要读取的本地路径
        if (Directory.Exists(dataPath)) Directory.Delete(dataPath, true);
        Directory.CreateDirectory(dataPath);

        //MainUtil.Log("正在解包文件:>Assembly-CSharp.dll");
        //MainUtil.Log(assemblySavePath);
        //MainUtil.Log(assemblyReadPath);
        //if (Application.platform == RuntimePlatform.Android)
        //{
        //    WWW www = new WWW(assemblyReadPath);
        //    yield return www;
        //    if (www.error != null)
        //    {
        //        MainUtil.Log(www.error);
        //    }
        //    if (www.isDone)
        //    {
        //        File.WriteAllBytes(assemblySavePath, www.bytes);
        //    }
        //    yield return 0;
        //}
        //else File.Copy(assemblyReadPath, assemblySavePath, true);


        //读取工程内版本控制文件的路径
        string infile = resPath + "version.txt";
        //输出到本地平台的版本控制文件的路径
        string outfile = dataPath + "version.txt";
        if (File.Exists(outfile)) File.Delete(outfile);

        MainUtil.Log("正在解包文件:>version.txt");
        MainUtil.Log(infile);
        MainUtil.Log(outfile);
        if (Application.platform == RuntimePlatform.Android)
        {
            WWW www = new WWW(infile);
            yield return www;
            if (www.error != null) {
                MainUtil.Log(www.error);
            }
            if (www.isDone)
            {
                File.WriteAllBytes(outfile, www.bytes);
            }
            yield return 0;
        }
        else File.Copy(infile, outfile, true);
        yield return new WaitForEndOfFrame();

        //释放所有文件到数据目录
        string[] files = File.ReadAllLines(outfile);
        foreach (var file in files)
        {
            string[] fs = file.Split('|');
            infile = resPath + fs[0];  //
            outfile = dataPath + fs[0];

            MainUtil.Log("正在解包文件:>" + fs[0]);
            //MainUtil.Log("正在解包文件所处源in path:>" + infile);
            //MainUtil.Log("正在解包文件所处目标out path:>" + outfile);

            string dir = Path.GetDirectoryName(outfile);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);

            if (Application.platform == RuntimePlatform.Android)
            {
                WWW www = new WWW(infile);
                yield return www;
                if (www.error != null)
                {
                    MainUtil.Log(www.error);
                }
                if (www.isDone)
                {
                    File.WriteAllBytes(outfile, www.bytes);
                    //MainUtil.Log("origin path:" + www.url + "   size:" + www.size + "   targetPath:" + outfile);
                }
                yield return 0;
            }
            else
            {
                if (File.Exists(outfile))
                {
                    File.Delete(outfile);
                }
                File.Copy(infile, outfile, true);
                MainUtil.Log(outfile.ToString());
            }
            yield return new WaitForEndOfFrame();
        }
        MainUtil.Log("解包完成！！！！！！！");
        yield return new WaitForSeconds(0.1f);
        
        //释放完成，开始启动更新资源
        StartCoroutine(OnUpdateResource());
    }
    

    /// <summary>
    /// 启动更新下载
    /// 直接将最新的文件更新到设备本地持久化路径
    /// </summary>
    IEnumerator OnUpdateResource()
    {
        if (!MainConst.UpdateMode)
        {
            StartCoroutine(OnResourceInited());
            yield break;
        }
        string dataPath = MainConfigPath.PersistentDataPath_IO();  //本地平台数据目录
        string url = MainConst.resServerUrl;
        string message = string.Empty;
        string random = System.DateTime.Now.ToString("yyyymmddhhmmss");
        string listUrl = url + "version.txt?v=" + random;
        MainUtil.Log("LoadUpdate---->>>" + listUrl);

        WWW www = new WWW(listUrl); yield return www;
        if (www.error != null)
        {
            MainUtil.Log(www.error);
            yield break;
        }
        if (!Directory.Exists(dataPath))
        {
            Directory.CreateDirectory(dataPath);
        }
        MainUtil.Log("下载最新的版本文件,大小:" + www.bytes.Length);
        //服务器版本文件直接覆盖本地的
        File.WriteAllBytes(dataPath + "version.txt", www.bytes);
        string filesText = www.text;
        //解析获得所有的纳入版本控制的文件信息
        string[] files = filesText.Split('\n');

        for (int i = 0; i < files.Length; i++)
        {
            if (string.IsNullOrEmpty(files[i])) continue;
            string[] keyValue = files[i].Split('|');
            string fileName = keyValue[0];
            string localfile = (dataPath + fileName).Trim();
            string path = Path.GetDirectoryName(localfile);
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string fileUrl = url + fileName + "?v=" + random;
            bool canUpdate = !File.Exists(localfile);
            if (!canUpdate)
            {
                //服务器MD5
                string remoteMd5 = keyValue[1].Trim();
                //本地MD5
                string localMd5 = MainUtil.md5file(localfile);//再计算一次，因为旧版本的MD5在version被覆盖后已经没有了
                canUpdate = !remoteMd5.Equals(localMd5);
                if (canUpdate) File.Delete(localfile);
            }
            if (canUpdate)
            {   //本地缺少文件
                MainUtil.Log("downloading,更新最新文件>>>>>>>>>>>>>" + fileUrl);
                
                www = new WWW(fileUrl); yield return www;
                if (www.error != null) {
                    OnUpdateFailed(path + " : " + fileUrl +" : "+ www.error);
                    yield break;
                }
                File.WriteAllBytes(localfile, www.bytes);

                //这里都是资源文件，此处可启动线程下载更新
                //BeginDownload(fileUrl, localfile);
                //while (!(IsDownOK(localfile))) { yield return new WaitForEndOfFrame(); }
            }
        }
        yield return new WaitForEndOfFrame();

        MainUtil.Log("更新完成!!");

        StartCoroutine(OnResourceInited());
    }

    void OnUpdateFailed(string file)
    {
        Debug.LogError("更新资源失败!>"+file);
    }

    ///// <summary>
    ///// 是否下载完成
    ///// </summary>
    //bool IsDownOK(string file)
    //{
    //    return downloadFiles.Contains(file);
    //}

    ///// <summary>
    ///// 线程下载
    ///// </summary>
    //void BeginDownload(string url, string file)
    //{     //线程下载
    //    object[] param = new object[2] { url, file };

    //    ThreadEvent ev = new ThreadEvent();
    //    ev.Key = NotiConst.UPDATE_DOWNLOAD;
    //    ev.evParams.AddRange(param);
    //    ThreadManager.AddEvent(ev, OnThreadCompleted);   //线程下载
    //}

    ///// <summary>
    ///// 线程完成
    ///// </summary>
    ///// <param name="data"></param>
    //void OnThreadCompleted(NotiData data)
    //{
    //    switch (data.evName)
    //    {
    //        case NotiConst.UPDATE_EXTRACT:  //解压一个完成
    //            //
    //            break;
    //        case NotiConst.UPDATE_DOWNLOAD: //下载一个完成
    //            downloadFiles.Add(data.evParam.ToString());
    //            break;
    //    }
    //}

    /// <summary>
    /// 资源初始化结束
    /// </summary>
    public IEnumerator OnResourceInited()
    {
//#if ASYNC_MODE
//            resourceManager.Initialize(AppConst.AssetDir, delegate() {
//                Debug.Log("Initialize OK!!!");
//                this.OnInitialize();
//            });
//#else
//        yield return StartCoroutine(resourceManager.Initialize());
//        this.OnInitialize();
//#endif
        yield return StartCoroutine(MainFacade.Instance.ResourceMgr.Initialize());
        this.OnInitialize();
    }

    void OnInitialize() {
        MainUtil.Log("资源初始化完毕,初始化游戏逻辑");
        //MainFacade.Instance.SoundMgr.PlayBacksound(Application.dataPath+"/GameResources/sound/lie");
        //MainFacade.Instance.IlrMgr.OnHotFixLoaded();
        MainFacade.Instance.LuaMgr.StartLua();
    }
}
